package com.tvunetworks.center.user.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.model.dto.CheckAuthDTO;
import com.tvunetworks.center.common.model.dto.instance.ApiParam;
import com.tvunetworks.center.common.util.EndecryptUtil;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.gs.model.Device;
import com.tvunetworks.center.user.constant.UserApiConstant;
import com.tvunetworks.center.user.constant.UserConstant;
import com.tvunetworks.center.user.mapper.CustomizedUserGroupMapper;
import com.tvunetworks.center.user.model.User;
import com.tvunetworks.center.user.model.param.api.AccessSessionParam;
import com.tvunetworks.center.user.model.param.api.ListBookingChannelParam;
import com.tvunetworks.center.user.model.param.api.ListGroupParam;
import com.tvunetworks.center.user.model.result.ResultConstant;
import com.tvunetworks.center.user.model.vo.UserApiParam;
import com.tvunetworks.center.user.model.vo.api.ListGroupVo;
import com.tvunetworks.center.user.service.UserApiService;
import com.tvunetworks.center.user.service.UserDeviceService;
import com.tvunetworks.center.user.service.UserHttpService;
import com.tvunetworks.center.user.service.feign.AccessFeignService;
import com.tvunetworks.center.user.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

/**
 * @program: tvucc-aggregator
 * @description: user api impl
 * @author Kevin_Li
 * @create: 2019-10-10 18:51
 **/
@Slf4j
@Service
public class UserApiServiceImpl implements UserApiService {

    @Autowired
    private AccessFeignService accessFeignService;
    @Autowired
    private UserHttpService userHttpService;
    @Autowired
    private CustomizedUserGroupMapper customizedUserGroupMapper;
    @Autowired
    private UserDeviceService userDeviceService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ExtServiceImpl extService;
    @Autowired
    private UserServiceImpl userService;

    @Override
    public Result getSession(UserApiParam userApiParam) {
        String type = userApiParam.getType();
        if(type.equalsIgnoreCase(UserApiConstant.XML_PARAM)){
            //XML的需要手动checkAuth
            Result<Void> checkAuthResult = checkAuth(userApiParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
        }
        return userHttpService.getSession(userApiParam.getEmail(), userApiParam.getPwd());
    }

    @Override
    public Result addExt(UserApiParam addExtParam) {
        String type = addExtParam.getType();
        if(type.equalsIgnoreCase(UserApiConstant.XML_PARAM)){
            //XML的需要手动checkAuth
            Result<Void> checkAuthResult = checkAuth(addExtParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
        }
        String userIdBySession = getUserIdBySession(addExtParam.getSessionId());
        User user = userService.getById(userIdBySession);
        if (user == null) {
            return ResultUtil.error("81000102", "User not exist");
        }
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(user, loginUser);
        return extService.addExtToUser(loginUser, addExtParam.getExtName(), addExtParam.getExtUrl(), "Ext", "",null);
    }

    @Override
    public String accessSession(AccessSessionParam param) {
        String email = param.getEmail();
        String password = param.getPassword();
        // 通过缓存获取 session，防止频繁访问 userservice
        String key = UserConstant.RedisKey.CACHE_API_SESSION + EndecryptUtil.MD5(email + password);
        String session = (String)redisUtil.get(key);
        if (session != null) {
            return session;
        }
        if (StringUtils.isBlank(email) && StringUtils.isBlank(password)) {
            ServerException.Exception(ResultUtil.paramErrorInfo());
        }
        Result<String> sessionResult = userHttpService.getSession(email, password);
        if (sessionResult.assertSuccess()) {
            session = sessionResult.getResult();
            // 将结果保存到 redis
            redisUtil.set(key, session, 10L);
            return session;
        }
        ServerException.Exception(ResultConstant.BookingAPI.GET_SESSION_FAILED);
        return null;
    }

    @Override
    public PageInfo<ListGroupVo> listGroup(ListGroupParam param) {
        String session = param.getSession();
        if (StringUtils.isBlank(session)) {
            ServerException.Exception(ResultUtil.paramErrorInfo());
        }
        String userId = this.getUserIdBySession(session);
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<ListGroupVo> list = customizedUserGroupMapper.listGroup(userId, param.getGroup());
        return new PageInfo<>(list);
    }


    @Override
    public PageInfo<Device> listBookingChannel(ListBookingChannelParam param) {
        String session = param.getSession();
        if (StringUtils.isBlank(session)) {
            ServerException.Exception(ResultUtil.paramErrorInfo());
        }
        String userId = this.getUserIdBySession(session);
        param.setUserId(userId);
        return userDeviceService.pageBookingChannel(param);
    }

    private Result<Void> checkAuth(ApiParam apiParam){
        CheckAuthDTO checkAuthDTO = apiParam.convertToCheckAutonotCheckTimestamp();
        checkAuthDTO.setFunction("default");
        return accessFeignService.checkAuth(checkAuthDTO);
    }


    private String getUserIdBySession(String session){
        Result<LoginUser> userResult = null;
        try {
            userResult = userHttpService.userserviceGetUserInfo(session);
        } catch (IOException e) {
            log.error(e.toString(), e);
            ServerException.Exception(ResultConstant.BookingAPI.INVALID_SESSION.setResult("UserserviceGetUserInfo exception"));
        }
        if (!userResult.assertSuccess()) {
            ServerException.Exception(ResultConstant.BookingAPI.INVALID_SESSION.setResult("UserserviceGetUserInfo failed"));
        }
        LoginUser loginUser = userResult.getResult();
        if (loginUser == null) {
            ServerException.Exception(ResultConstant.BookingAPI.INVALID_SESSION);
        }
        return loginUser.getId();
    }
}
